/**
 * @file drv_pwm.c
 * @brief PWM驱动实现 - 简化版 (仅底层输出控制)
 * @date 2025-11-04
 */

#include "drv_pwm.h"
#include "user_config.h"

/* 外部变量声明 (来自STM32 HAL) ----------------------------------------------*/
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim14;

/* 私有类型定义 -------------------------------------------------------------*/

/**
 * @brief PWM通道配置
 */
typedef struct {
    TIM_HandleTypeDef *htim;    /* 定时器句柄 */
    uint32_t tim_channel;       /* TIM通道 (TIM_CHANNEL_x) */
} pwm_config_t;

/**
 * @brief PWM通道状态
 */
typedef struct {
    uint16_t duty;              /* 当前占空比 (0-10000) */
    bool enabled;               /* 是否启用 */
} pwm_state_t;

/* 私有变量定义 -------------------------------------------------------------*/

/**
 * @brief PWM通道配置表
 */
static const pwm_config_t s_pwm_configs[PWM_CH_MAX] = {
    {&htim3, TIM_CHANNEL_4},    /* PWM_CH1: PB1 - TIM3_CH4 */
    {&htim3, TIM_CHANNEL_2},    /* PWM_CH2: PA7 - TIM3_CH2 */
    {&htim3, TIM_CHANNEL_1},    /* PWM_CH3: PA6 - TIM3_CH1 */
    {&htim2, TIM_CHANNEL_1},    /* PWM_CH4: PA5 - TIM2_CH1 */
    {&htim14, TIM_CHANNEL_1},   /* PWM_CH5: PA4 - TIM14_CH1 */
    {&htim2, TIM_CHANNEL_4},    /* PWM_CH6: PA3 - TIM2_CH4 */
    {&htim2, TIM_CHANNEL_3},    /* PWM_CH7: PA2 - TIM2_CH3 */
    {&htim2, TIM_CHANNEL_2}     /* PWM_CH8: PA1 - TIM2_CH2 */
};

/**
 * @brief PWM通道状态
 */
static pwm_state_t s_pwm_states[PWM_CH_MAX];

/* 私有函数声明 -------------------------------------------------------------*/
static uint32_t duty_to_compare(uint16_t duty);

/* 公共函数实现 -------------------------------------------------------------*/

/**
 * @brief 初始化PWM驱动
 */
int drv_pwm_init(void) {
    /* 初始化所有通道为空闲状态 */
    for (uint8_t i = 0; i < PWM_CH_MAX; i++)
    {
        s_pwm_states[i].duty = 0;
        s_pwm_states[i].enabled = false;
    }

    return 0;
}

/**
 * @brief 启动PWM输出
 */
int drv_pwm_start(pwm_channel_e ch, uint16_t duty) {
    if (ch >= PWM_CH_MAX)
    {
        return -1;
    }

    if (duty > PWM_DUTY_MAX)
    {
        duty = PWM_DUTY_MAX;
    }

    const pwm_config_t *cfg = &s_pwm_configs[ch];

    /* 设置比较值 */
    uint32_t compare = duty_to_compare(duty);
    __HAL_TIM_SET_COMPARE(cfg->htim, cfg->tim_channel, compare);

    /* 启动PWM输出 */
    if (HAL_TIM_PWM_Start(cfg->htim, cfg->tim_channel) != HAL_OK)
    {
        return -1;
    }

    /* 更新状态 */
    s_pwm_states[ch].duty = duty;
    s_pwm_states[ch].enabled = true;

    return 0;
}

/**
 * @brief 停止PWM输出
 */
int drv_pwm_stop(pwm_channel_e ch) {
    if (ch >= PWM_CH_MAX)
    {
        return -1;
    }

    const pwm_config_t *cfg = &s_pwm_configs[ch];

    /* 停止PWM输出 */
    if (HAL_TIM_PWM_Stop(cfg->htim, cfg->tim_channel) != HAL_OK)
    {
        return -1;
    }

    /* 更新状态 */
    s_pwm_states[ch].enabled = false;
    s_pwm_states[ch].duty = 0;

    return 0;
}

/**
 * @brief 设置PWM占空比
 */
int drv_pwm_set_duty(pwm_channel_e ch, uint16_t duty) {
    if (ch >= PWM_CH_MAX)
    {
        return -1;
    }

    if (!s_pwm_states[ch].enabled)
    {
        return -1; /* 通道未启动 */
    }

    if (duty > PWM_DUTY_MAX)
    {
        duty = PWM_DUTY_MAX;
    }

    const pwm_config_t *cfg = &s_pwm_configs[ch];

    /* 更新比较值 */
    uint32_t compare = duty_to_compare(duty);
    __HAL_TIM_SET_COMPARE(cfg->htim, cfg->tim_channel, compare);

    /* 更新状态 */
    s_pwm_states[ch].duty = duty;

    return 0;
}

/**
 * @brief 获取板号对应的第一悬停占空比
 * @note 根据编译模式返回不同精度的值
 */
uint16_t drv_pwm_get_board_duty_1(uint8_t board_id)
{
#if MIDI2_INTERNAL_16BIT_VEL
    /* 高精度模式 (0-2181) */
    switch (board_id)
    {
        case 1:  return PWM_FIRST_HOLD_DUTY_B1_HR;
        case 2:  return PWM_FIRST_HOLD_DUTY_B2_HR;
        case 3:  return PWM_FIRST_HOLD_DUTY_B3_HR;
        case 4:  return PWM_FIRST_HOLD_DUTY_B4_HR;
        case 5:  return PWM_FIRST_HOLD_DUTY_B5_HR;
        case 6:  return PWM_FIRST_HOLD_DUTY_B6_HR;
        case 7:  return PWM_FIRST_HOLD_DUTY_B7_HR;
        case 8:  return PWM_FIRST_HOLD_DUTY_B8_HR;
        case 9:  return PWM_FIRST_HOLD_DUTY_B9_HR;
        case 10: return PWM_FIRST_HOLD_DUTY_B10_HR;
        case 11: return PWM_FIRST_HOLD_DUTY_B11_HR;
        default: return 0;
    }
#else
    /* 传统模式 (0-10000) */
    switch (board_id)
    {
        case 1:  return PWM_FIRST_HOLD_DUTY_B1;
        case 2:  return PWM_FIRST_HOLD_DUTY_B2;
        case 3:  return PWM_FIRST_HOLD_DUTY_B3;
        case 4:  return PWM_FIRST_HOLD_DUTY_B4;
        case 5:  return PWM_FIRST_HOLD_DUTY_B5;
        case 6:  return PWM_FIRST_HOLD_DUTY_B6;
        case 7:  return PWM_FIRST_HOLD_DUTY_B7;
        case 8:  return PWM_FIRST_HOLD_DUTY_B8;
        case 9:  return PWM_FIRST_HOLD_DUTY_B9;
        case 10: return PWM_FIRST_HOLD_DUTY_B10;
        case 11: return PWM_FIRST_HOLD_DUTY_B11;
        default: return 0;
    }
#endif
}

/**
 * @brief 获取板号对应的第二悬停占空比
 * @note 根据编译模式返回不同精度的值
 */
uint16_t drv_pwm_get_board_duty_2(uint8_t board_id)
{
#if MIDI2_INTERNAL_16BIT_VEL
    /* 高精度模式 (0-2181) */
    if (board_id >= 1 && board_id <= 2)
    {
        return PWM_SECOND_HOLD_DUTY_B1_2_HR;
    }
    else if (board_id >= 3 && board_id <= 4)
    {
        return PWM_SECOND_HOLD_DUTY_B3_4_HR;
    }
    else if (board_id >= 5 && board_id <= 6)
    {
        return PWM_SECOND_HOLD_DUTY_B5_6_HR;
    }
    else if (board_id >= 7 && board_id <= 9)
    {
        return PWM_SECOND_HOLD_DUTY_B7_9_HR;
    }
    else if (board_id >= 10 && board_id <= 11)
    {
        return PWM_SECOND_HOLD_DUTY_B10_11_HR;
    }
    else
    {
        return 0;
    }
#else
    /* 传统模式 (0-10000) */
    if (board_id >= 1 && board_id <= 2)
    {
        return PWM_SECOND_HOLD_DUTY_B1_2;
    }
    else if (board_id >= 3 && board_id <= 4)
    {
        return PWM_SECOND_HOLD_DUTY_B3_4;
    }
    else if (board_id >= 5 && board_id <= 6)
    {
        return PWM_SECOND_HOLD_DUTY_B5_6;
    }
    else if (board_id >= 7 && board_id <= 9)
    {
        return PWM_SECOND_HOLD_DUTY_B7_9;
    }
    else if (board_id >= 10 && board_id <= 11)
    {
        return PWM_SECOND_HOLD_DUTY_B10_11;
    }
    else
    {
        return 0;
    }
#endif
}

/**
 * @brief 停止所有PWM通道
 */
int drv_pwm_stop_all(void) {
    int ret = 0;

    for (uint8_t i = 0; i < PWM_CH_MAX; i++)
    {
        if (s_pwm_states[i].enabled)
        {
            if (drv_pwm_stop((pwm_channel_e)i) != 0)
            {
                ret = -1;
            }
        }
    }

    return ret;
}

/* 私有函数实现 -------------------------------------------------------------*/

/**
 * @brief 将占空比转换为定时器比较值
 * @param duty 占空比 (范围取决于精度模式)
 * @return 定时器比较值
 * @note 支持两种精度模式:
 *       - 传统模式: duty 范围 0-10000 (0.01% 精度)
 *       - 高精度模式: duty 范围 0-2181 (硬件全精度)
 *       自动根据 duty 值范围判断模式
 */
static uint32_t duty_to_compare(uint16_t duty)
{
    /* 从定时器获取周期 (TIM2和TIM3周期相同) */
    uint32_t period = __HAL_TIM_GET_AUTORELOAD(&htim2);
    uint32_t compare;

    /* 判断精度模式 */
    if (duty <= PWM_DUTY_MAX_HIGHRES)
    {
        /* 高精度模式: duty 直接对应硬件比较值 */
        compare = duty;
    }
    else
    {
        /* 传统模式: duty 范围 0-10000，需要转换 */
        compare = ((uint32_t)duty * period) / PWM_RESOLUTION;
    }

    /* 限制在有效范围内 */
    if (compare > period)
    {
        compare = period;
    }

    return compare;
}

/******************************** 文件结束 *********************************/
